/*
-------------------------------------------------

	Render.cpp

	Dmitriy Kuzmenko (Dgut)

-------------------------------------------------
*/

#include "Render.h"
#include "Common.h"
#include "OpenGL.h"
#include "Texture.h"
#define _USE_MATH_DEFINES
#include <math.h>

using namespace std;

namespace Autumn
{

Render::Render( void )
{
}

Render::~Render( void )
{
}

const bool Render::Init( void )
{
	glEnable( GL_TEXTURE_2D );
	glEnable( GL_BLEND );
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

	glEnableClientState( GL_VERTEX_ARRAY );
	glEnableClientState( GL_TEXTURE_COORD_ARRAY );

	tverts[ 0 ] = 0.f;
	tverts[ 1 ] = 0.f;
	
	tverts[ 2 ] = 1.f;
	tverts[ 3 ] = 0.f;
	
	tverts[ 4 ] = 1.f;
	tverts[ 5 ] = 1.f;
	
	tverts[ 6 ] = 0.f;
	tverts[ 7 ] = 1.f;

	return true;
}

void Render::Shutdown( void )
{
	for( map< string, Texture * >::iterator i = textures.begin(); i != textures.end(); i++ )
		delete i->second;
	for( map< string, Font * >::iterator i = fonts.begin(); i != fonts.end(); i++ )
		delete i->second;
}

void Render::Frame( void )
{
	//glClearColor( 1.f, 0.f, 0.f, 0.f );
	glClear( GL_COLOR_BUFFER_BIT );

	//gRender.SetProjection( gCommon.SPACE_WIDTH, gCommon.SPACE_HEIGHT );
}

Texture * const Render::GetTexture( const char * name )
{
	Texture * texture = textures[ name ];
	if( texture )
		return texture;

	return textures[ name ] = Texture2D::CreateStandart( name );
}

Font * const Render::GetFont( const char * name )
{
	Font * font = fonts[ name ];
	if( font )
		return font;

	return fonts[ name ] = new Font( ( string( "font/" ) + name + ".png" ).c_str(), ( string( "font/" ) + name + ".dat" ).c_str() );
}

void Render::SetTexture( const Texture * texture )
{
	texture->Bind();
}

void Render::SetFont( const Font * font )
{
	Render::font = font;
}

void Render::SetOrthogonalProjection( float width, float height )
{
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
#if defined WIN32
	glOrtho( 0., width, 0., height, -99999., 99999. );
#elif defined IPHONE
	glOrthof( 0., width, 0., height, -99999., 99999. );
	/*glOrthof( 0., height, 0., width, -99999., 99999. );
	if( screenOrientation == SO_LANDSCAPE_LEFT )
	{
		glRotatef( 90.f, 0.f, 0.f, 1.f );
		glTranslatef( 0.f, -height, 0.f );
	}
	else
	{
		glRotatef( -90.f, 0.f, 0.f, 1.f );
		glTranslatef( -width, 0.f, 0.f );
	}*/
#endif
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
}

void Render::SetPerspectiveProjection( float fov )
{
	static const double zNear = 4.;
	static const double zFar = 4096.;

	double xmin, xmax, ymin, ymax, aspect;

	aspect = ( double )gCommon.WIDTH / gCommon.HEIGHT;

	ymax = zNear * tan( fov * M_PI / 360.0 );
	ymin = -ymax;

	xmin = ymin * aspect;
	xmax = ymax * aspect;

	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
}

void Render::PushMatrix( void )
{
	glPushMatrix();
}

void Render::PopMatrix( void )
{
	glPopMatrix();
}

void Render::Identity( void )
{
	glLoadIdentity();
}

void Render::SetColor( float red, float green, float blue, float alpha )
{
	glColor4f( red, green, blue, alpha );
}

void Render::Rotate( float angle )
{
	Rotate( angle, 0.f, 0.f, 1.f );
}

void Render::Rotate( float angle, float x, float y, float z )
{
	glRotatef( angle * 180.f / M_PI, x, y, z );
}

void Render::Scale( float scale )
{
	glScalef( scale, scale, 1.f );
}

void Render::Scale( float x, float y, float z )
{
	glScalef( x, y, z );
}

void Render::Translate( float x, float y, float z )
{
	glTranslatef( x, y, z );
}

void Render::DrawRectangle( float x, float y, float width, float height )
{
	glVertexPointer( 2, GL_FLOAT, 0, verts );
	glTexCoordPointer( 2, GL_FLOAT, 0, tverts );

	verts[ 0 ] = x;
	verts[ 1 ] = y;

	verts[ 2 ] = x + width;
	verts[ 3 ] = y;

	verts[ 4 ] = x + width;
	verts[ 5 ] = y + height;

	verts[ 6 ] = x;
	verts[ 7 ] = y + height;

	glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
}

void Render::DrawPolygon( float * verts, float * tverts, int numPoints )
{
	glVertexPointer( 2, GL_FLOAT, 0, verts );
	glTexCoordPointer( 2, GL_FLOAT, 0, tverts );

	glDrawArrays( GL_TRIANGLE_FAN, 0, numPoints );
}

void Render::Print( Font::HorizontalAlign ha, Font::VerticalAlign va, float x, float y, float scale, const char * text/*, ...*/ )
{
	/*static char buffer[ 1024 ] = { 0 };

	va_list	arg;
	
	va_start( arg, text );
	vsnprintf( buffer, sizeof( buffer ), text, arg );
	va_end( arg );*/

	font->Print( ha, va, x, y, scale, /*buffer*/text );
}

}	// namespace Autumn